5W - 이스티오 mTLS와 SPIFFE

개요

이스티오와 같은 서비스 메시에서는 여러 독립된 컴포넌트들이 상호작용을 해야 하며, 그렇기 때문에 다양한 보안적 고려 요소가 생긴다.
일단 통신 간 암호화는 거의 필수 고려 사항이고, 통신 주체 간 인증, 트래픽 인가 등의 요소도 빼놓을 수 없다.
이스티오에서는 관련된 커스텀 리소스와 기능들을 제공하고 있다.
이번 노트에서는 먼저 통신 간 암호화, 그리고 tls 통신 간 신원을 설정하는 Peer Authentication 리소스를 먼저 알아볼 것이다.

이 노트를 편하게 읽기 위해서는 mTLS, X.509가 무엇인지는 알고 있어야 한다.

사전 지식

위 그림은 각 프록시가 X.509 인증서를 받아서 서로 mTLS 통신을 하는 흐름을 간단하게 담고 있다.
이번 문서에서는 이 내용을 집중적으로 다룰 것이다.

이스티오 메시 속에서 모든 서비스는 고유한 신원을 받는다.
이것은 X.509 인증서를 기반으로 이뤄지며, 이 인증서는 서비스의 신원이자 통신 간 암호화의 수단이 되기도 한다.
이 인증서를 발급하는 주체는 istiod로, 자신의 개인키를 이용해 서명한 인증서를 각 서비스에게 전달한다.
istiod에서는 각 서비스가 인증서 서명 요청(CSR)을 할 수 있도록 gRPC 서비스를 노출하고 있다(과거 Citadel).
데이터 플레인 사이드카가 배치될 때, pilot-agent는 개인키와 CSR을 만들어 istiod로부터 인증서를 발급받는다.
엔보이가 가동되면 엔보이는 에이전트가 노출한 소켓 파일에 SDS(Secret Discovery Service) api를 통해 인증서와 개인키를 가져와 세팅한다.
에이전트는 인증서의 서명을 주기적으로 체크하며 필요 시 갱신하는 작업을 수행한다.

SPIFFE

구체적으로 인증서를 발급하는 과정을 알아보기 전에 간단하게 SPIFFE에 대해 알아본다.

Secure Production Identity Framework For Everyone.
다양한 소프트웨어 시스템 환경에서 동적으로, 일관되게 보안적으로 고유한 신원을 제공하기 위해 개발된 오픈소스 표준이다.
이스티오는 이 표준을 바탕으로 인증서 발급 아키텍처를 구축하고 있다.

온프레미스를 넘어 다양한 클라우드 환경이 나오면서 이질적이고 다양한 환경에서 고유한 신원을 제공하고자 하는 수요가 발생했다.
그래서 스피페는 구체적으로 여러 복합적인 환경에서 워크로드에 고유한 신원을 제공하는 것을 목표로 개발됐다.

워크로드?

이때 워크로드는 단일 목적을 가진 소프트웨어의 집합을 말한다.
즉 같은 역할을 하는 여러 웹서버는 하나의 워크로드라고 친다는 것이다.
워크로드 참고.

워크로드의 신원을 부여하기 위해서는 단순히 네트워크 식별자를 사용할 수는 없다.
여기에 실행되는 인스턴스의 고유한 정보를 이용하는 것도 불가능한데, 하나의 워크로드여도 여러 개의 복제본이 다양한 노드에서 실행될 수 있기 때문이다.
이를 위해 스피페에서는 자신만의 특별한 방법을 마련했는데..

SPIFFE ID

그것은 바로 스피페 ID이다.
스피페 ID는 URI의 한 종류로서 네트워크 환경에서 마음대로 지정할 수 있는 하나의 스킴이다.

spiffe://example.org/ns/default/sa/backend

스피페 id는 이렇게 생겼다.
조금 더 구체적인 형식을 보자.

spiffe://{신뢰 도메인}/{워크로드 식별자}

신뢰 도메인(trust domain)은 스피페를 구축한 인프라 전체를 아우르는 도메인을 말한다.
쿠버네티스라면 보통 클러스터 도메인(cluster.local)을 말한다.
같은 도메인으로부터 신원 증명을 발급 받은 모든 워크로드는 같은 도메인으로부터 검증될 수 있다.

워크로드 식별자 부분은 스피페를 구현하는 개체가 마음대로 정할 수 있다.
가령 위에 쿠버네티스 환경에서는 ns/{네임스페이스}/sa/{서비스어카운트}라고 지정한 것처럼 말이다.

참고로, 스피페 ID는 워크로드에 대해 부여되는 게 기본이고 이게 워크로드에서 활용되지만 이를 발급 받는 과정을 위해 노드에 대해서도 부여되긴 한다.

SVID(Spiffe Verifiable Identity Document)

위 스피페 id가 식별자로 쓰이긴 할 텐데, 도대체 어떻게 이걸 통신 간에 적용할 것인가?
스피페에서는 워크로드가 자신의 신원을 증명할 수 있는 증명서를 SVID라는 개념으로 추상화시켰다.
추상화됐다고 하는 이유는 SVID 자체가 어떤 특정한 증명서 형식인 게 아니라 기존에 존재하던 형식을 활용하여 구성되기 때문이다.
스피페 id는 다음의 두 신원 증명 수단으로 제작될 수 있다.

스피페 id가 쏙 들어간 저런 형식들을 그냥 SVID라 부르는 것이다.
그러니 앞으로 SVID를 발급받는다 하면 저것 중에 하나 발급받는 거겠거니 생각하면 된다.
image.png
x509의 경우 그냥 이렇게 X509v3 Subject Alternative Name 하위로 URI로 spiffe ID가 들어가는 식이다.
image.png
이 사이트에 들어가서 x509 인증서를 그대로 갖다 박으면 SVID의 정보를 예쁘게 확인할 수 있게 해준다.

Workload API

SVID라는 것은 결국 흔히 통신 간 신원을 증명하는 수단으로 활용되는 인증서나 토큰에 추가적인 정보가 들어간 형태일 뿐이라는 것인데, 그렇다면 이러한 인증서나 토큰을 어떻게 발급받을 것이냐가 마지막 관건이 된다.
지금까지의 개념을 보자면, 결국 워크로드가 어디로부턴가 SVID를 받아서 활용해야 한다.

스피페에서는 이 방식을 다음과 같은 흐름으로 정리했다.
일단 워크로드는 신뢰 도메인을 기반으로 인증서를 발급해주는 중앙 서버로부터 SVID를 받아야 하는 상황이다.

즉, 워크로드는 에이전트 - 서버를 거쳐서 SVID를 받게 되는 건데 이러한 방식은 워크로드가 스피페의 세부 구현 여부를 몰라도 되도록 추상화한다는 이점이 있다.
스피페는 다양하고 이질적인 환경에서도 통일된 신원을 제공하기 위한 프레임워크라고 했다.
이때 환경마다 복잡하고 세분화될 수 있는 각종 신원 마련 수단을 워크로드 입장에서는 몰라도 되도록 구조를 잡았고, 이제 스피페를 활용하려는 조직에서는 이 워크로드 API에 대해서만 알고 관련한 구현을 하면 된다.
참고로 워크로드 api는 gRPC로 정의된다고 한다.[1]

SPIFFE를 조금 더 깊게 이해하려면 스피페를 만든 팀이 구현한 아키텍쳐인 SPIRE를 자세히 보면 도움이 된다.
여기에서 더 깊게 다루진 않겠다.

이스티오 인증서 발급 과정

다시 돌아와서, 이스티오는 위 스피페의 표준에 따라 인증서를 발급하는 아키텍처를 구축했다.
그래서 여기에서 발급되는 인증서는 SVID라고 하는, SPIFFE 양식을 따르는 인증서이다.
이스티오 환경에서 스피페 방식을 준수하고 따르는 것에는 다음의 이점이 있다.

그렇다면 구체적으로 어떻게 이스티오에서는 인증서를 발급받고 이를 활용하는가?

스피페에서 지정한 SPIRE의 방식과 살짝 비슷하면서도 상당히 다르다.

서비스 어카운트가 워크로드 식별자라는 것은 곧 서비스 어카운트가 워크로드의 단위라는 것이다.
그런데 SPIRE에서는 워크로드 증명 과정이 에이전트 단계에서 끝나는데, 이스티오에서는 istiod가 토큰 리뷰 요청을 날린다!
이스티오를 기준으로 SPIRE와의 몇 가지 차이를 정리하자면,

실제로 해당 신원을 사용하는 워크로드인 엔보이는 발급 과정에 관여하지 않으며 워크로드 별 고유한 신원을 제공한다는 기본 스피페의 철학에는 충실하기에 이스티오는 스피페의 구현체 중 하나로서 탄탄히 구실을 해내고 있다고 말할 수 있다.

참고로 SPIRE 오퍼레이터를 설치해서 이스티오의 모든 인증서 발급과 관리 과정을 SPIRE를 거치도록 하는 것도 가능하다.[2]
이 경우 엔보이의 SDS api가 설정을 받아갈 유닉스 도메인 소켓을 SPIFFE CSI 드라이버가 마운팅해준다.
그리고 기본 설계에 충실하게 에이전트는 노드 별로 배치된 채 증명서를 발급한다.
물론 SPIRE 서버가 워크로드들을 미리 알 수 있도록 등록을 자동화 추가적인 커스텀 리소스를 만들어주긴 해야 한다.

PeerAuthenticiation

아무튼 위의 방법으로 각 서비스는 인증서를 받게 된다.
엔보이는 이제 이 인증서를 통해 통신을 하게 되는데 이때 mTLS를 어떻게 할지에 대해 설정할 수 있는 리소스가 바로 PeerAuthentication이다.
참고로 이 리소스는 요청을 받는 엔보이의 리스너에 설정이 들어가는 것이기 때문에 mTLS에 대해 만약 클라 측에서 커스텀을 하고 싶다면 이스티오 데스티네이션룰을 설정해야 한다.

이스티오의 정책 관련 리소스가 대부분 그러한데, 정책의 적용 범위가 3가지로 나뉜다.

지역적인 설정일수록 우선순위가 더 높은 방식이고, 네임스페이스나 메시 단위 리소스는 해당 범위에 하나만 존재할 수 있다.
여러 개를 둔다고 해도 가장 오래된 것만 적용되는 방식이다.
워크로드 대상 정책 역시 여러 개가 매칭이 되는 케이스라면 오래된 정책이 적용된다.

그럼 어떤 식으로 작성하는가?

apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: default
  namespace: foo
spec:
  selector:
    matchLabels:
      app: finance
  mtls:
    mode: STRICT
  portLevelMtls:
    8080:
      mode: DISABLE

selector로 워크로드를 선택하고, mtls에서 tls 세팅, portLevelMtls에서 포트 레벨 tls 설정을 한다.
(당연하지만 포트 레벨 tls는 서비스 포트가 아니라 워크로드 기준이다.)

tls 모드는 다음과 같다.

apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: "example-workload-policy"
  namespace: "foo"
spec:
  selector:
     matchLabels:
       app: example-app
  portLevelMtls:
    80:
      mode: DISABLE

UNSET의 예시를 들자면, 이건 워크로드의 80 포트에 대해서는 mtls를 비활성화한다.
그러나 foo 네임스페이스 단위의 정책이 따로 설정돼있다면 다른 포트들에 대해서는 해당 정책이 적용될 것이다.

mTLS

mTLS가 어떤 식으로 이뤄지는지 간단하게만 짚자면..

mutual TLS는 클라이언트의 신원도 인증서를 기반으로 검증하는 추가 단계가 포함된 프로토콜이다. 별도로 분리된 프로토콜은 아니고, 그냥 위의 동작 흐름 상에서 클라 인증서를 교환하는 과정이 조금 추가될 뿐이다. 일반 사용자가 브라우저를 이용할 때 사용되진 않고, 서버 간 통신을 할 때 서로를 신뢰하기 위한 수단으로 사용된다. mTLS는 서버의 신원만 확인하던 기존 tls와 달리 클라의 신원도 서버에서 요구한다. 이를 통해 서로 통신하는 상대가 누군지 정확하게 특정 가능하다는 특징이 있다. # 실습 진행 본격적으로 PeerAuthentication을 건드리는 실습을 해본다. 여기에 추가적으로 위에서 설명한 spiffe 인증서가 발급되는 과정으로 생긴 파일들도 확인해볼 것이다. ## 환경 세팅 ```yaml apiVersion: install.istio.io/v1alpha1 kind: IstioOperator spec: profile: default components: pilot: k8s: env: - name: PILOT_FILTER_GATEWAY_CLUSTER_CONFIG value: "true" ingressGateways: - name: istio-ingressgateway enabled: true k8s: service: type: NodePort ports: - name: http port: 80 targetPort: 8080 nodePort: 30000 - name: https port: 443 targetPort: 8443 nodePort: 30005 externalTrafficPolicy: Local meshConfig: outboundTrafficPolicy: mode: ALLOW_ANY enableTracing: true defaultProviders: metrics: - prometheus tracing: [] accessLogFile: /dev/stdout values: global: variant: distroless pilot: env: ENABLE_NATIVE_SIDECARS: true ``` 항상 세팅 방식은 동일하다. KIND 역시 마찬가지. ```sh # resolve domain resolve = "catalog.istioinaction.io:30000:127.0.0.1" resolve = "webapp.istioinaction.io:30000:127.0.0.1" resolve = "simpleweb.istioinaction.io:30000:127.0.0.1"

silent

silent

대신 이번 실습부터는 로컬에서 curl을 날릴 때 조금 더 편하게 하기 위해 conf 파일을 만들었다.
```sh
curl -K curl.conf {주소}

이렇게 인자를 전달하면 여기에 사전 세팅한 내용들을 인자로 전달해서 curl을 날릴 수 있다.
/etc/hosts에 도메인 매번 넣었다 빼기는 귀찮고, 그렇다고 curl에 매번 인자 길게 넣기 귀찮은 나 같은 사람에게 매우 유용한 방식이다!

k create ns istioinaction
k label ns istioinaction istio-injection=enabled
k ns istioinaction

항상 하던 대로 istioinaction 네임스페이스를 만들고..

kubectl apply -f services/catalog/kubernetes/catalog.yaml -n istioinaction
kubectl apply -f services/webapp/kubernetes/webapp.yaml -n istioinaction
kubectl apply -f services/webapp/istio/webapp-catalog-gw-vs.yaml -n istioinaction
kubectl apply -f ch9/sleep.yaml -n default

여태 책에서 나온 실습 예제를 넣어준다.
sleep 파드를 default에 배치하는데, 이건 서비스 메시가 적용되지 않은 네임스페이스에서의 통신 상황을 가정하는 것이다.
단순하게 통신을 날리는 용으로 띄운 파드로 netshoot을 쓰건 우분투를 쓰건 상관 없다.
image.png
default 네임스페이스는 사이드카 인젝션이 일어나지 않은 상황이다.
이때 sleep 파드의 통신을 제한하거나 통과시키는 설정을 해볼 것이다.

sleep 파드에서 통신이 날아가는 과정을 키알리로 간단하게 보자면..

watch 'kubectl -n default exec deploy/sleep -c sleep -- curl -s webapp.istioinaction/api/catalog -o /dev/null -w "%{http_code}\n"'

image.png
unknown으로부터 요청이 날아온다.
image.png
사이드카가 주입되지 않은 sleep 파드에서의 요청은 인증서가 없는 클라로부터의 통신이기에 unknown으로 표시된다.
image.png

peer authentication 리소스 활용

메시 범위 mtls 강제

apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
  name: "default"
  namespace: "istio-system"
spec:
  mtls:
    mode: STRICT

전역적으로 mtls를 강제해본다.
image.png
정책을 적용하자마자 위와 같이 요청에 에러가 발생한다.
이제 최소한 sleep 파드에서 통신을 하기 위해서는 자신도 인증서를 제출할 수 있어야만 한다.
image.png
로그를 뜯어보면 갑자기 NR(Non-Route)이라고 하면서 아예 트래픽이 막혀버리는 것을 확인할 수 있다.

워크로드 permissive 허용

apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
  name: "webapp"
  namespace: "istioinaction"
spec:
  selector:
    matchLabels:
      app: "webapp"
  mtls:
    mode: PERMISSIVE

조금 더 지엽적인 설정이 우선 적용된다.
이번엔 webapp으로 가는 요청이 mtls를 희망하나 못 하더라도 그대로 요청이 성립되게 한다.
image.png
이제 webapp으로의 요청은 성공한다.
image.png
그러나 catalog로 직접 요청을 날려보면 이렇게 실패하는 것을 볼 수 있다.

 istioctl pc listener webapp-7c96945758-9jzxt --port 15006 -ojson | fx 

image.png
외부의 트래픽을 받는 포트는 15006이기 때문에 한번 확인해봤는데, tls가 강제되면 모든 필터체인 리스트에 transportSocket 필드가 생기며 filterChainMatch는 tls로 고정된다.
image.png
반면 permissive 모드라면 중간 필터 체인 중 하나는 위와 같이 ChainMatch에 raw_buffer로 표시되며, 이 필터에는 transportSocket 필드도 설정되지 않는다.
image.png
mtls가 설정된 필드를 조금 더 자세히 보면, 간단한 검증에 대한 설정이 들어간 게 보인다.
이때 재밌는 것이 바로 spiffe 기반으로 SAN을 매칭한다는 것이다.
PeerAuthN의 경우 클러스터 내부의 통신에 대한 설정이기 때문에 모든 적용 대상은 결국 SVID를 가지고 있을 것이고, 이를 기반으로 위 조건에서 걸리게 될 것을 짐작할 수 있다.

spiffe 인증서 확인

그럼 실제로 엔보이가 받은 인증서는 어떻게 생겼을까?
image.png
istioctl을 통해 쉽게 현재 프록시에 위치한 인증서 값을 꺼내볼 수 있다.
하나씩 꺼내보자.

istioctl pc secret debug -ojson | jq '.dynamicActiveSecrets[1].secret.validationContext.trustedCa.inlineBytes' -r | base64 -d | openssl x509 -text -noout

image.png
첫번째로 istiod의 루트 인증서를 꺼내본다.
그냥 별 볼일 없는 루트 인증서긴 하다.

istioctl pc secret debug -ojson | jq '.dynamicActiveSecrets[0].secret.tlsCertificate.certificateChain.inlineBytes' -r | base64 -d | openssl x509 -noout -text

image.png
다음, 엔보이가 사용할 인증서를 꺼내보면 extensions 필드에 아주 흥미로운 값을 볼 수 있다!
X509v3 Subject Alternative Name 하위로 URI로 spiffe ID가 들어가고 있다.
현재 이 인증서는 cluster.locl이라는 신뢰 도메인 아래, istioinaction 네임스페이스의 default 서비스어카운트의 신원을 나타내는 SVID라는 것을 여기에서 확인할 수 있다.
image.png
이 사이트에 들어가서 x509 인증서를 그대로 갖다 박으면 SVID의 정보를 예쁘게 확인할 수 있게 해준다.
고마워요 텔포맨

func Verify() (bool, error) {
	serverCert, err := os.ReadFile("x509/server.crt")
	if err != nil {
		panic(err)
	}
	rootCert, err := os.ReadFile("x509/root.crt")
	if err != nil {
		panic(err)
	}
	block, _ := pem.Decode(serverCert)
	if block == nil {
		return false, errors.New("failed to parse certificate PEM")
	}

	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		panic(err)
	}

	roots := x509.NewCertPool()
	ok := roots.AppendCertsFromPEM(rootCert)
	if !ok {
		return false, errors.New("failed to parse root certificate")
	}

	opts := x509.VerifyOptions{
		Roots: roots,
	}

	if _, err := cert.Verify(opts); err != nil {
		fmt.Println(err)
	}
	return true, nil
}

고 언어를 공부하는 김에 간단하게 인증서 검사 함수를 만들었다.
image.png
이제 프록시가 생성될 때, pilot agent가 뱉는 로그를 조금 더 이해할 수 있다.
엔보이가 실행되기 전, 에이전트는 JWT 토큰을 먼저 읽는다.
그리고 CA인 istiod에 인증서를 요청한다.
그리고 자체적으로 SDS 서버를 기동하는데, 이건 그냥 var/run/secrets/workload-spiffe-uds/socket 소켓을 리스닝하는 프로세스이다.
엔보이는 SDS api를 이곳으로 날리게 될 것이다.

distroless 컨테이너 진입 후 확인 - 삽질

kubectl debug -it debug \
  --image=nicolaka/netshoot \
  --target=istio-proxy \
  --share-processes \
  --profile sysadmin \
  -- zsh

아예 컨테이너 안 속으로 들어가서 정보를 조금 더 자세히 보도록 한다.
distroless 이미지를 쓰고 있는 관계로 네임스페이스를 공유하는 임시 컨테이너를 만들어 붙였다.
권한 문제로부터 자유롭게 돌아다녀야 하기 때문에 sysadmin의 권한을 주었다.

참고로 조금의 삽질을 하면서 방법을 찾아냈다.
image.png
image.png
처음 들어오면 기본적으로 네트워크 네임스페이스는 공유하고 있는 상태이다.
image.png
이 상태로 모든 정보를 뜯어볼 수 있으면 참 좋겠지만, 아쉽게도 파일시스템을 공유하고 있지 않은 상태이다.

nsenter -t 1 

참고로 기본적으로 네임스페이스에 접속하는 명령어는 이건데, distroless 이미지의 경우에는 아예 /bin/sh조차 없기 때문에 해당 명령이 먹히지 않았다.
image.png
그렇다고 방법이 없을쏘냐, 뚫으면 다 길이 있기 마련이다.
보다시피 프로세스를 공유받았다는 것은, 프로세스 디렉토리에 해당 정보가 표시된다는 말이다.
중간에 하늘색(소프트 링크 파일) root가 있는데, 저게 1번 프로세스의 루트 파일시스템을 나타내는 파일이다.

chroot /proc/1/root /bin/bash

그러면 아예 루트 디렉토리를 바꾸는 명령어로 distroless 이미지의 파일시스템을 볼 수 있게 된다.
그런데 그렇게 해도 ls, cat 등의 명령어가 없어서 안 속을 뜯어보는 것은 쉬운 일이 아니다.
image.png
근데... 굳이 루트 디렉토리를 바꿀 이유가 없다 ㅋㅋ
image.png
자, 이제 슬슬 보고 싶은 것들이 보이기 시작한다.
image.png
위에서 봤던, SDS api를 주고받는다는 소켓 파일을 찾아냈다.

ss -xep

image.png
소켓 파일 정보는 명령어로도 볼 수 있다.
이렇게보면 엔보이와 에이전트가 어떻게 통신하고 있는지가 조금 더 선명하게 확인된다.

하는 김에 컨트롤 플레인 통신 경로도 추적해보기

스터디를 처음 시작할 때 아주 간단하게 프록시 컨테이너를 뜯어보았다.
그때도 소켓파일을 보았는데, 이제 머리가 조금 굵어졌으니 명확하게 어떻게 구조가 이뤄져있는 건지도 추적해보자.
image.png
이전에도 말했지만 컨트롤 플레인에서는 15012 포트를 통해 각종 설정을 노출해주고 있다.
그런데 사실 해당 포트와 통신을 하고 있는 것은, 엔보이가 아니라 파일럿 에이전트이다.
그렇다면 에이전트는 어떻게 엔보이에게 실질적인 설정들을 전달해줄 수 있을까?
image.png
에이전트는 이렇게 두 가지 유닉스 소켓 파일을 열어두고 있는데, 엔보이 설정에 이게 어떻게 들어있는지를 보면 된다.

istioctl pc bootstrap debug

image.png
엔보이 부트스트랩 파일을 보면 dynamicResource에 ADS 설정을 받을 때 xds-grpc라는 클러스터로 연결하는 것을 알 수 있는데,
image.png
해당 클러스터는 사실 에이전트가 열고 있는 소켓 파일이다.
image.png
SDS 설정을 받아올 때 사용되는 클러스터 역시 마찬가지이다.

왜 이런 구조로 돼있는가 처음에는 의아했는데, 파일 디스크립터를 보고 살짝 예상이 되는 부분이 있었다.
파일럿 에이전트는 엔보이 프록시가 동작하기 이전에 환경을 세팅할 책임을 가지고 먼저 소켓 파일을 만들어둔다.
컨트롤 플레인과 실제로 통신을 하는 시점은 소켓 파일 생성 시점보다 늦는데, 이는 에이전트가 엔보이 설정을 위한 프록시로서 동작하고 있다는 것을 명확하게 보여준다.
파일럿 에이전트가 엔보이를 위한 프록시로서 동작하여 얻는 이점은 두 가지가 있다고 생각한다.

토큰 확인

image.png
이번에는 이스티오를 위해 발급된 jwt 토큰을 보자.
image.png
이 토큰은 어디까지나 api서버가 발급한다는 것에 유의하자.
이 jwt 토큰의 청중 대상은 istio-ca, 즉 istiod 내부의 인증 모듈(과거 Citadel)이다.
image.png
파드에 사이드카가 주입될 당시 변형되는 양식을 보면, 사이드카가 사용할 볼륨이 projected volume 형태로 들어가는 것을 확인할 수 있다.
이게 위 토큰인데, 이렇게 써있다고 이스티오가 토큰 생성에 관여하는 건 사실 전혀 아니다.
그냥 istiod는 토큰에 청중을 istio-ca라고만 써주세요 api 서버에 부탁한 것에 불과하다.

결론

서비스 간 통신에서 암호화를 하게 되면 내부망에 침입한 공격자가 있더라도 패킷 탈취를 하는 것을 막을 수 있다.
이스티오에서는 그저 암호화를 하는데에 그치지 않고 상호 인증서를 배치하여 서로의 신원을 명확하게 확인할 수 있게 도와준다.
이걸 이용해서 아예 트래픽 인가 정책을 짤 수도 있는데, 그건 다음 노트에서 알아본다.

이전 글, 다음 글

다른 글 보기

이름 index noteType created
1W - 서비스 메시와 이스티오 1 published 2025-04-10
1W - 간단한 장애 상황 구현 후 대응 실습 2 published 2025-04-10
1W - Gateway API를 활용한 설정 3 published 2025-04-10
1W - 네이티브 사이드카 컨테이너 이용 4 published 2025-04-10
2W - 엔보이 5 published 2025-04-19
2W - 인그레스 게이트웨이 실습 6 published 2025-04-17
3W - 버츄얼 서비스를 활용한 기본 트래픽 관리 7 published 2025-04-22
3W - 트래픽 가중치 - flagger와 argo rollout을 이용한 점진적 배포 8 published 2025-04-22
3W - 트래픽 미러링 패킷 캡쳐 9 published 2025-04-22
3W - 서비스 엔트리와 이그레스 게이트웨이 10 published 2025-04-22
3W - 데스티네이션 룰을 활용한 네트워크 복원력 11 published 2025-04-26
3W - 타임아웃, 재시도를 활용한 네트워크 복원력 12 published 2025-04-26
4W - 이스티오 메트릭 확인 13 published 2025-05-03
4W - 이스티오 메트릭 커스텀, 프로메테우스와 그라파나 14 published 2025-05-03
4W - 오픈텔레메트리 기반 트레이싱 예거 시각화, 키알리 시각화 15 published 2025-05-03
4W - 번외 - 트레이싱용 심플 메시 서버 개발 16 published 2025-05-03
5W - 이스티오 mTLS와 SPIFFE 17 published 2025-05-11
5W - 이스티오 JWT 인증 18 published 2025-05-11
5W - 이스티오 인가 정책 설정 19 published 2025-05-11
6W - 이스티오 설정 트러블슈팅 20 published 2025-05-18
6W - 이스티오 컨트롤 플레인 성능 최적화 21 published 2025-05-18
8W - 가상머신 통합하기 22 published 2025-06-01
8W - 엔보이와 iptables 뜯어먹기 23 published 2025-06-01
9W - 앰비언트 모드 구조, 원리 24 published 2025-06-07
9W - 앰비언트 헬름 설치, 각종 리소스 실습 25 published 2025-06-07
7W - 이스티오 메시 스케일링 26 published 2025-06-09
7W - 엔보이 필터를 통한 기능 확장 27 published 2025-06-09

관련 문서

이름 noteType created
Cert Manager knowledge 2025-03-15
TLS downgrade attack knowledge 2024-06-20
openssl knowledge 2025-01-18
TLS knowledge 2025-04-16
PKI knowledge 2025-03-10
cfssl knowledge 2025-01-23
Istio PeerAuthentication knowledge 2025-05-04
SPIFFE knowledge 2025-05-04
6W - PKI 구조, CSR 리소스를 통한 api 서버 조회 published 2025-03-15
E-api 서버 감사 topic/explain 2025-01-21
E-이스티오 메시 스케일링 topic/explain 2025-06-08

참고


  1. https://github.com/spiffe/spiffe/blob/main/standards/SPIFFE_Workload_API.md ↩︎

  2. https://istio.io/latest/docs/ops/integrations/spire/ ↩︎